package com.hnust.listener;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cleveroom.core.CRMDevice;
import com.cleveroom.utils.Tools;
import com.hnust.entity.Device;
import com.hnust.entity.Position;
import com.hnust.entity.SensorData;
import com.hnust.entity.code.SensorCode;
import com.hnust.listener.abstracts.SensorListener;
import com.hnust.service.DeviceService;
import com.hnust.service.PositionService;
import com.hnust.service.SensorCodeService;
import com.hnust.service.SensorDataService;
import com.hnust.utils.SimpleTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 创建人：zhangRuWang
 * 创建时间：2022/4/19
 * 描述：传感器监听器，监听到对应传感器后，将信息存储到device和sensor_data两张表中
 */
@Component
public class CleveroomSensorListener extends SensorListener {
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private PositionService positionService;
    @Autowired
    private SensorDataService sensorDataService;
    @Autowired
    private SensorCodeService sensorCodeService;

    @Override
    protected void onDeviceChange(CRMDevice crmDevice) {
        //这里主要监听传感器数据的变化
        String deviceUid=crmDevice.getUid();
        QueryWrapper<Device> deviceQuery=new QueryWrapper<>();
        deviceQuery.eq("uid",deviceUid);
        Device sensor=deviceService.getOne(deviceQuery);
        //新建传感器对象，插入传感器数据表
        SensorData sensorData=new SensorData();
        sensorData.setPositionId(sensor.getPositionId());
        sensorData.setState(1);
        //主要填充 Uid,sensorCode,传感器名字，test_state,数据，数据单元
        this.sensorHandler(sensorData,crmDevice);
        sensorDataService.save(sensorData);
    }

    @Override
    protected void onAddNewDevice(CRMDevice crmDevice) {
        String deviceUid=crmDevice.getUid();
        QueryWrapper<Device> deviceQuery=new QueryWrapper<>();
        deviceQuery.eq("uid",deviceUid);
        Device sensor=deviceService.getOne(deviceQuery);
        SensorData sensorData=new SensorData();
        if(sensor!=null){
            //说明之前有保存到设备表中
            sensor.setState(1);
            deviceService.updateById(sensor);
            //新增传感器时，依旧会产生数据，插入到传感器数据表中
            sensorData.setPositionId(sensor.getPositionId());
        }else{
            //说明之前没有保存到数据库中,第一次接入设备
            //设置地理位置
            Position position=new Position();
            position.setRegionCode(0);position.setBuildCode(0);
            position.setFloorCode(crmDevice.getD3());
            position.setRoomCode(crmDevice.getD4());
            positionService.save(position);
            //新建设备对象
            Device newSensor=new Device();
            //填充对应的值
            newSensor.setPositionId(position.getId());
            newSensor.setUid(crmDevice.getUid());
            //设置设备代码
            int D2=crmDevice.getD2();
            if(D2==198){
                if(crmDevice.getD6()==20){
                    newSensor.setCode(1981);
                }else if(crmDevice.getD6()==21){
                    newSensor.setCode(1982);
                }else{
                    newSensor.setCode(1983);
                }
            }else{
                newSensor.setCode(D2);
            }
            //设备其它参数
            newSensor.setState(1);
            newSensor.setDeviceType("传感器");
            newSensor.setDeviceIns(SimpleTools.crmDeviceToString(crmDevice));
            //插入设备表
            deviceService.save(newSensor);
            //填充传感器位置信息
            sensorData.setPositionId(position.getId());
        }
        sensorData.setState(1);
        //主要填充 Uid,sensorCode,传感器名字，数据，数据单元
        this.sensorHandler(sensorData,crmDevice);
        sensorDataService.save(sensorData);
    }

    /**
     *处理传感器数据，转换为统一格式
     */
    public void sensorHandler(SensorData sensorData, CRMDevice crmDevice){
        sensorData.setUid(crmDevice.getUid());
        sensorData.setSensorCode(crmDevice.getD2());
        //判断设备
        int D2=crmDevice.getD2();
        if(D2>=120&&D2<=128){
            //有三个字节表示数据的类型
            this.parseThreeDataSensor(sensorData,crmDevice);
        }else if(D2==198){
            //有三种状态转换的传感器
            this.parseThreeStateSensor(sensorData,crmDevice);
        }else if(D2>=194&&D2<=197){
            this.parseTwoStateSensor(sensorData,crmDevice);
        }
    }

    /**
     *由三个字节表示数据的传感器解析
     * D5	D6	D7
     * 数据（低位）	数据2	数据3（高位）
     */
    public void parseThreeDataSensor(SensorData sensorData, CRMDevice crmDevice){
        LambdaQueryWrapper<SensorCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq( SensorCode::getCode, crmDevice.getD2());
        SensorCode sensorCode=sensorCodeService.getOne(queryWrapper);
        if(sensorCode!=null){
            if(sensorCode.getSensorName().contains("传感器")){
                sensorData.setTestState(sensorCode.getSensorName().split("传感器")[0]);
            }
            sensorData.setSensorName(sensorCode.getSensorName());
            sensorData.setUnit(sensorCode.getUnit());
            sensorData.setData(SimpleTools.convertToData(
                    crmDevice.getD5(),crmDevice.getD6(),
                    crmDevice.getD7()
            ));
        }else{
            sensorData.setSensorName("未知设备");
        }
    }

    /**
     *有三种状态的传感器的解析
     */
    public void parseThreeStateSensor(SensorData sensorData, CRMDevice crmDevice){
        int D5=crmDevice.getD5();
        int D6=crmDevice.getD6();
        //温度/湿度/亮度传感器
        if(D6==20){
            //温度
            sensorData.setSensorName("温度传感器");
            sensorData.setTestState("温度");
            //这里使用多一位来区分不同的传感器
            sensorData.setSensorCode(1981);
            byte[] bytes = Tools.byte2bit(D5);
            if (bytes[7] == 1) {
                //负摄氏度
                StringBuilder sb=new StringBuilder();
                for(int i=bytes.length-2;i>=0;i--){
                    sb.append(bytes[i]);
                }
                sensorData.setData(-Long.parseUnsignedLong(sb.toString(),2));
            }else{
                sensorData.setData((long) (D5));
            }
            sensorData.setUnit("ºC");
        }else if(D6==21){
            //亮度
            sensorData.setSensorName("亮度传感器");
            //这里使用多一位来区分不同的传感器
            sensorData.setSensorCode(1982);
            sensorData.setTestState("亮度");
            sensorData.setData((long) (D5*3));
            sensorData.setUnit("LUX");
        }else{
            //湿度
            sensorData.setSensorName("湿度传感器");
            //这里使用多一位来区分不同的传感器
            sensorData.setSensorCode(1983);
            sensorData.setTestState("湿度");
            sensorData.setData((long) (D5));
            sensorData.setUnit("RH%");
        }
    }

    /**
     *有两种状态转换的传感器的解析
     */
    public void parseTwoStateSensor(SensorData sensorData, CRMDevice crmDevice){
        int D2=crmDevice.getD2();
        int D6=crmDevice.getD6();
        int D5=crmDevice.getD5();
        if(D2==194){
            sensorData.setSensorName("门磁传感器");
            String sb = (D6 == 255 ? "分区布防状态-" : D6 == 85 ? "布防状态-" : "撤防状态-") +
                    (D5 == 255 ? "开门" : "关门");
            sensorData.setTestState(sb);
        }else if(D2==195){
            sensorData.setSensorName("人体移动传感器");
            String sb = (D6 == 255 ? "分区布防状态-" : D6 == 85 ? "布防状态-" : "撤防状态-") +
                    (D5 == 255 ? "有人经过" : "没人经过");
            sensorData.setTestState(sb);
        }else{
            sensorData.setSensorName(D2==196?"烟气传感器":"燃气传感器");
            String sb = (D5 == 255 ? "有报警" : "没报警");
            sensorData.setTestState(sb);
        }
    }
}
